package com.aisino.springai.demos.chat.controller;


import com.aisino.springai.demos.chat.util.CommonUtil;
import com.aisino.springai.demos.web.User;
import com.alibaba.fastjson.JSONObject;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * @author guochuantao
 * @version 1.0
 * @description
 * @since 2025/3/26 上午9:29
 */
@RestController
@RequestMapping("/chat")
@Slf4j
public class ChatController {
    // 原子API
    @Resource
    private ChatModel chatModel;
    // 直接提供AI服务
    @Resource
    private ChatClient chatClient;

    /**
     * 简单对话 get是可以接受复杂数据json的
     *
     * @param param 参数
     * @return 回答内容
     */
    @GetMapping("/simple")
    public String simpleChat(@RequestBody JSONObject param) {
        // 接收并校验参数
        String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！");
        // 构建chatClient
        ChatClient.Builder builder = ChatClient.builder(chatModel);
        ChatClient chatClient = builder.defaultSystem("你是一个精通Java、Python的程序大佬。").build();
        System.out.println("输入内容：" + inputInfo);
        String content = chatClient.prompt().user(inputInfo).call().content();
        System.out.println("回答内容：" + content);
        return content;
    }

    @PostMapping(value = "/stream", produces = "text/event-stream;charset=UTF-8")
    public Flux<ServerSentEvent<String>> streamChat(@RequestBody JSONObject param) {
        // 接收并校验参数
        String inputInfo = CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！");

        return chatModel.stream(new Prompt(inputInfo))
                .map(response -> ServerSentEvent.<String>builder()
                        .data(response.getResult().getOutput().getContent()).build())
                .doOnComplete(() -> log.info("响应完成！"))
                .doOnError(e -> log.error("响应异常：", e));
    }


    //========================================  SpringAIAlibaba API =============================================

    /**
     * 简单对话 get是可以接受复杂数据json的
     *
     * @param param 参数
     * @return 回答内容
     */
    @GetMapping("/simple2content")
    public String simple2content(@RequestBody JSONObject param) {
        return chatClient.prompt(CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！"))
                .call().content();
    }

    /**
     * {
     * "result": {
     * "metadata": {
     * "finishReason": "STOP",
     * "contentFilters": [],
     * "empty": true
     * },
     * "output": {
     * "messageType": "ASSISTANT",
     * "metadata": {
     * "finishReason": "STOP",
     * "role": "ASSISTANT",
     * "id": "85d6c155-935f-97e8-ae57-94471beb7dfe",
     * "messageType": "ASSISTANT"
     * },
     * "toolCalls": [],
     * "media": [],
     * "content": "我现在的角色是一个**博学的智能聊天助手**，专门根据用户的提问提供准确、全面和有用的回答。无论你是想了解知识、寻求建议、创作内容，还是单纯想聊聊天，我都会尽力满足你的需求。如果有任何问题，请随时向我提问！ 😊",
     * "text": "我现在的角色是一个**博学的智能聊天助手**，专门根据用户的提问提供准确、全面和有用的回答。无论你是想了解知识、寻求建议、创作内容，还是单纯想聊聊天，我都会尽力满足你的需求。如果有任何问题，请随时向我提问！ 😊"
     * }
     * },
     * "metadata": {
     * "id": "85d6c155-935f-97e8-ae57-94471beb7dfe",
     * "model": "",
     * "rateLimit": {
     * "requestsRemaining": 0,
     * "requestsLimit": 0,
     * "tokensRemaining": 0,
     * "tokensLimit": 0,
     * "requestsReset": "PT0S",
     * "tokensReset": "PT0S"
     * },
     * "usage": {
     * "generationTokens": 61,
     * "totalTokens": 159,
     * "promptTokens": 98
     * },
     * "promptMetadata": [],
     * "empty": true
     * },
     * "results": [
     * {
     * "metadata": {
     * "finishReason": "STOP",
     * "contentFilters": [],
     * "empty": true
     * },
     * "output": {
     * "messageType": "ASSISTANT",
     * "metadata": {
     * "finishReason": "STOP",
     * "role": "ASSISTANT",
     * "id": "85d6c155-935f-97e8-ae57-94471beb7dfe",
     * "messageType": "ASSISTANT"
     * },
     * "toolCalls": [],
     * "media": [],
     * "content": "我现在的角色是一个**博学的智能聊天助手**，专门根据用户的提问提供准确、全面和有用的回答。无论你是想了解知识、寻求建议、创作内容，还是单纯想聊聊天，我都会尽力满足你的需求。如果有任何问题，请随时向我提问！ 😊",
     * "text": "我现在的角色是一个**博学的智能聊天助手**，专门根据用户的提问提供准确、全面和有用的回答。无论你是想了解知识、寻求建议、创作内容，还是单纯想聊聊天，我都会尽力满足你的需求。如果有任何问题，请随时向我提问！ 😊"
     * }
     * }
     * ]
     * }
     */
    @GetMapping("/simple3chatResponse")
    public ChatResponse simpleChat3ChatResponse(@RequestBody JSONObject param) {
        return chatClient.prompt(CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！"))
                .call().chatResponse();
    }

    /**
     * 输入
     * {
     * "inputInfo":"帮我生成一个user对象，包含姓名、年龄、性别"
     * }
     * <p>
     * 返回
     * {
     * "name": "张三",
     * "age": 25
     * }
     * <p>
     * [
     * {
     * "name": "张三",
     * "age": 25
     * }
     * ]
     */
    @GetMapping("/simple4entity")
    public List<User> simpleChat4entity(@RequestBody JSONObject param) {
        return chatClient.prompt(CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！"))
                .call()
                // .entity(User.class);
                .entity(new ParameterizedTypeReference<List<User>>() {
                });

    }

    /**
     * flux 流式返回结果 支持实时获取生成过程的分块响应
     */
    @GetMapping("/simple5flux")
    public Flux<String> simple5flux(@RequestBody JSONObject param) {
        return chatClient.prompt().user(CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！"))
                .stream().content();
    }


    /**
     * function calling
     * {
     *   "inputInfo":"计算一下78 * 2等于多少"
     * }
     *
     * 计算结果是 78 * 2 = 156。
     *
     * multiplyFunction会被调用
     */
    @GetMapping("/simple6function")
    public Flux<String> simple6function(@RequestBody JSONObject param) {
        return chatClient.prompt()
                .user(CommonUtil.getAndCheck(param, "inputInfo", "请输入内容！"))
                .functions("multiplyFunction", "addFunction")
                // .tools("multiplyFunction", "addFunction")
                .stream().content();
    }

}
